package com.think.cloud.thinkshop.mall.service.order.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.think.cloud.thinkshop.common.enums.RabbitMessageTypeEnum;
import com.think.cloud.thinkshop.common.enums.payment.PaymentStatusEnum;
import com.think.cloud.thinkshop.common.enums.user.SwitchEnum;
import com.think.cloud.thinkshop.mall.controller.admin.index.dto.StatisticalTrendViewDTO;
import com.think.cloud.thinkshop.mall.controller.admin.memberuser.dto.MemberOrderConsumeViewDTO;
import com.think.cloud.thinkshop.mall.controller.admin.message.dto.MessageTemplateReplaceDTO;
import com.think.cloud.thinkshop.mall.controller.admin.order.vo.*;
import com.think.cloud.thinkshop.mall.controller.app.order.dto.AppOrderLogDTO;
import com.think.cloud.thinkshop.mall.convert.order.OrderConvert;
import com.think.cloud.thinkshop.mall.domain.LogisticsLog;
import com.think.cloud.thinkshop.mall.domain.memberuser.MemberUser;
import com.think.cloud.thinkshop.mall.domain.order.Order;
import com.think.cloud.thinkshop.mall.domain.order.OrderLog;
import com.think.cloud.thinkshop.mall.enums.logisticslog.LogisticsOrderTypeEnum;
import com.think.cloud.thinkshop.mall.enums.message.MessageTemplateEnum;
import com.think.cloud.thinkshop.mall.enums.order.OrderOperateTypeEnum;
import com.think.cloud.thinkshop.mall.enums.order.OrderOperateUserTypeEnum;
import com.think.cloud.thinkshop.mall.enums.order.OrderStatusEnum;
import com.think.cloud.thinkshop.mall.mapper.order.OrderMapper;
import com.think.cloud.thinkshop.mall.rabbit.producer.MessageProducer;
import com.think.cloud.thinkshop.mall.service.memberuser.IMemberUserService;
import com.think.cloud.thinkshop.mall.service.message.IMessageTemplateService;
import com.think.cloud.thinkshop.mall.service.order.ILogisticsLogService;
import com.think.cloud.thinkshop.mall.service.order.IOrderDetailService;
import com.think.cloud.thinkshop.mall.service.order.IOrderLogService;
import com.think.cloud.thinkshop.mall.service.order.IOrderService;
import com.think.cloud.thinkshop.mall.service.websitesetting.IWebsiteSettingService;
import com.think.common.core.exception.util.ServiceExceptionUtil;
import com.think.common.core.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.think.common.core.exception.enums.ErrorCode.ORDER_NOT_DELETE_ERROR;
import static com.think.common.core.exception.enums.ErrorCode.ORDER_NOT_REPEAT_SHIPMENT_ERROR;

/**
 * 订单Service业务层处理
 *
 * @author zkthink
 * @date 2024-05-23
 */
@Service
public class OrderServiceImpl implements IOrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private IOrderDetailService iOrderDetailService;

    @Autowired
    private IOrderLogService iOrderLogService;

    @Autowired
    private MessageProducer messageProducer;

    @Autowired
    private IWebsiteSettingService websiteSettingService;

    @Autowired
    private ILogisticsLogService logisticsLogService;
    @Autowired
    private IMemberUserService memberUserService;
    @Autowired
    private IMessageTemplateService messageTemplateService;

    private Order findById(Long id){
        return orderMapper.selectById(id);
    }
    /**
     * 查询订单
     *
     * @param id 订单主键
     * @return 订单
     */
    @Override
    public OrderInfoRespVO selectOrderById(Long id) {
        Order order = this.findById(id);
        OrderInfoRespVO vo = OrderConvert.INSTANCE.convert1(order);
        vo.setTotalTaxation(vo.getTaxation().add(vo.getPostageTaxation())); // 计算总税费
        MemberUser memberUser = memberUserService.selectMemberUserById(order.getUserId());
        //下单用户
        vo.setOrderUser(memberUser.getUsername());
        // 查询订单明细
        List<OrderDetailRespVO> orderDetails =  this.getOrderDetails(Arrays.asList(id));
        vo.setDetails(orderDetails);
        // 查询操作日志
        List<OrderLogRespVO> orderLogs = iOrderLogService.selectOrderLogListByOrderId(id);
        vo.setLogs(orderLogs);
        return vo;
    }

    /**
     * 查询订单列表
     *
     * @param vo 订单
     * @return 订单
     */
    @Override
    public List<OrderPageRespVO> selectOrderList(OrderPageReqVO vo) {
        List<OrderPageRespVO> orders = orderMapper.selectOrderList(vo);
        if (CollectionUtil.isNotEmpty(orders)) {
            List<Long> orderIds = orders.stream().map(OrderPageRespVO::getId).collect(Collectors.toList());
            // 查询订单明细
            List<OrderDetailRespVO> orderDetails = this.getOrderDetails(orderIds);
            Map<Long, List<OrderDetailRespVO>> orderDetailMap =
                    orderDetails.stream().collect(Collectors.groupingBy(OrderDetailRespVO::getOrderId));
            orders.forEach(res -> res.setDetails(orderDetailMap.get(res.getId())));
        }
        return orders;
    }

    // 查询订单明细
    private List<OrderDetailRespVO> getOrderDetails(List<Long> orderIds){
        return iOrderDetailService.selectOrderDetailListByOrderIds(orderIds);
    }

    /**
     * 发货
     *
     * @param vo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delivery(OrderDeliveryReqVO vo, LoginUser loginUser) {
        Long orderId = vo.getId();
        Order currentOrder = this.findById(orderId);
        if (!OrderStatusEnum.AWAITING_SHIPMENT.getValue().equals(currentOrder.getStatus()))
            throw ServiceExceptionUtil.exception(ORDER_NOT_REPEAT_SHIPMENT_ERROR);

        Order updateOrder = OrderConvert.INSTANCE.convert(vo);
        updateOrder.setStatus(OrderStatusEnum.AWAITING_RECEIPT.getValue());
        orderMapper.updateById(updateOrder);
        // 订单日志保存
        iOrderLogService.insertOrderLog(buildOrderLog(new AppOrderLogDTO(orderId, loginUser.getUserid(),
                loginUser.getUsername(), OrderOperateTypeEnum.SHIP_BY_MERCHANT.getValue())));
        //注册物流单号
        logisticsLogService.register(orderId, LogisticsOrderTypeEnum.ORDINARY_ORDER.getCode(),
                updateOrder.getDeliveryId(), updateOrder.getDeliveryName(), updateOrder.getDeliverySn());
        //订单自动收货消息
        Integer automaticReceiptDays = websiteSettingService.getCache().getAutomaticReceiptDays();
        messageProducer.sendDelayedMessage(orderId.toString(),
                RabbitMessageTypeEnum.DELAY_ORDER_AUTOMATIC_RECEIPT_DAYS,
                automaticReceiptDays,
                TimeUnit.DAYS
        );
        //收货前24小时的通知
        if (automaticReceiptDays > 1) {
            messageProducer.sendDelayedMessage(orderId.toString(),
                    RabbitMessageTypeEnum.DELAY_ORDER_AUTO_RECEIPT_NOTICE,
                    automaticReceiptDays - 1,
                    TimeUnit.DAYS
            );
        }
        List<OrderDetailRespVO> orderDetails = this.getOrderDetails(Arrays.asList(orderId));
        String productInfo = orderDetails.stream()
                .map(detail -> detail.getProductName() + " " + detail.getSku())
                .collect(Collectors.joining("，"));
        // 发货消息通知
        MessageTemplateReplaceDTO param = MessageTemplateReplaceDTO
                .builder()
                .orderCode(currentOrder.getOrderCode())
                .orderId(orderId)
                .product(productInfo)
                .build();
        messageTemplateService.sendMessageText(MessageTemplateEnum.TEMPLATE_4, param, currentOrder.getUserId());
    }

    /**
     * 构建订单操作记录
     *
     * @param dto
     * @return
     */
    private OrderLog buildOrderLog(AppOrderLogDTO dto) {
        return OrderLog.builder().orderId(dto.getOrderId()).userId(dto.getUserId())
                .userType(OrderOperateUserTypeEnum.MERCHANT.getValue())
                .operateType(dto.getOperateType()).createBy(dto.getUserName()).build();
    }

    /**
     * 计算订单数量
     *
     * @param startTime 起始时间
     * @param endTime   结束时间
     * @return
     */
    @Override
    public Long orderCount(String startTime, String endTime) {
        return orderMapper.selectCount(statisticCondition(startTime, endTime));
    }

    @Override
    public List<StatisticalTrendViewDTO> orderCountTrend(String startTime, String endTime) {
        //创建订单就算订单数量了
        return orderMapper.orderCountTrend(statisticCondition(startTime, endTime));
    }

    @Override
    public double payUserCount(String startTime, String endTime) {
        return orderMapper.payUserCount(
                statisticPayCondition(startTime, endTime)
                        .eq(Order::getPaid, PaymentStatusEnum.PAYMENT_STATUS_PAID.getCode())
        );
    }

    /**
     * 统计的查询条件
     */
    private LambdaQueryWrapper<Order> statisticCondition(String startTime, String endTime) {
        return Wrappers.<Order>lambdaQuery()
                .ge(ObjectUtil.isNotNull(startTime), Order::getCreateTime, startTime)
                .le(ObjectUtil.isNotNull(startTime), Order::getCreateTime, endTime)
                ;
    }

    private LambdaQueryWrapper<Order> statisticPayCondition(String startTime, String endTime) {
        return Wrappers.<Order>lambdaQuery()
                .ge(ObjectUtil.isNotNull(startTime), Order::getPayTime, startTime)
                .le(ObjectUtil.isNotNull(startTime), Order::getPayTime, endTime)
                ;
    }

    /**
     * 计算营业额
     *
     * @param startTime 起始时间
     * @param endTime   结束时间
     * @return
     */
    @Override
    public Long turnoverTotal(String startTime, String endTime) {
        return orderMapper.getTurnoverTotal(startTime, endTime);
    }

    @Override
    public List<StatisticalTrendViewDTO> turnoverTotalTrend(String startTime, String endTime) {
        //已支付即是营收 ，0：未支付，1： 已支付
        statisticCondition(startTime, endTime).eq(Order::getPaid, PaymentStatusEnum.PAYMENT_STATUS_PAID.getCode());
        return orderMapper.getTurnoverTotalTrend(statisticCondition(startTime, endTime));
    }

    @Override
    public List<String> orderAmountRecord(String startTime, String endTime) {
        return orderMapper.orderAmountRecord(startTime, endTime);
    }

    @Override
    public JSONArray getLogistics(String deliveryId) {
        LogisticsLog logisticsLog = logisticsLogService.selectByDeliveryId(deliveryId);
        if (ObjectUtil.isNotNull(logisticsLog)) {
            return JSONUtil.parseArray(logisticsLog.getLogisticsInfo());
        }
        return new JSONArray();
    }

    @Override
    public Float orderConvertRate(String startTime, String endTime) {
        List<StatisticalTrendViewDTO> statisticalTrendViewDTOS = orderCountTrend(startTime, endTime);
        return null;
    }

    @Override
    public Float payConvertRate(String startTime, String endTime) {
        return null;
    }

    @Override
    public MemberOrderConsumeViewDTO userOrderConsumeView(Long userId) {
        return orderMapper.userOrderConsumeView(userId);
    }

    @Override
    public int deleteOrder(Long id) {
        // 查询订单
        Order order = this.findById(id);
        // 判断状态
        if (!(OrderStatusEnum.CANCELED.getValue().equals(order.getStatus()) ||
                OrderStatusEnum.COMPLETED.getValue().equals(order.getStatus()))) {
            throw ServiceExceptionUtil.exception(ORDER_NOT_DELETE_ERROR);
        }
        //用户删除之后才能后台删除
        if (order.getUserDel().equals(SwitchEnum.ACTIVE.getCode())) {
            throw ServiceExceptionUtil.exception(ORDER_NOT_DELETE_ERROR);
        }
        return orderMapper.deleteById(id);
    }
}
